package com.itcp.itelpicture.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itcp.itelpicture.common.BeanUtils;
import com.itcp.itelpicture.domain.dto.community.CommunityPostAddRequest;
import com.itcp.itelpicture.domain.dto.community.CommunityPostEditRequest;
import com.itcp.itelpicture.domain.dto.community.CommunityPostQueryRequest;
import com.itcp.itelpicture.domain.dto.file.UploadPictureResult;
import com.itcp.itelpicture.domain.po.PostTag;
import com.itcp.itelpicture.domain.po.Tag;
import com.itcp.itelpicture.domain.po.User;
import com.itcp.itelpicture.domain.po.community.CommunityPost;
import com.itcp.itelpicture.domain.vo.communityVo.CommunityPostVO;
import com.itcp.itelpicture.domain.vo.communityVo.PostDetailVO;
import com.itcp.itelpicture.enums.PostStatusEnum;
import com.itcp.itelpicture.enums.UserRoleEnum;
import com.itcp.itelpicture.exception.BusinessException;
import com.itcp.itelpicture.exception.ErrorCode;
import com.itcp.itelpicture.exception.ThrowUtils;
import com.itcp.itelpicture.manager.upload.FilePictureUpload;
import com.itcp.itelpicture.mapper.CommunityPostMapper;
import com.itcp.itelpicture.service.ICommunityPostService;
import com.itcp.itelpicture.service.IUserService;
import com.itcp.itelpicture.service.PostTagService;
import com.itcp.itelpicture.service.TagService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.itcp.itelpicture.constants.ReviewConstant.PASSED_IF_ADMIN;

@Slf4j
@Service
@RequiredArgsConstructor
public class CommunityPostServiceImpl extends ServiceImpl<CommunityPostMapper, CommunityPost>
        implements ICommunityPostService {

    private final IUserService userService;

    private final TagService tagService;

    private final PostTagService postTagService;

    private final FilePictureUpload filePictureUpload;

    @Override
    public void validCommunityPost(CommunityPost communityPost) {

    }

    @Override
    public CommunityPostVO getCommunityPostVO(CommunityPost communityPost) {
        // 1.获取登录用户
        Long userId = communityPost.getUserId();
        User user = userService.getById(userId);
        // 2.属性拷贝
        CommunityPostVO communityPostVO = BeanUtils.copyBean(communityPost, CommunityPostVO.class);
        // 3.设置用户信息
        communityPostVO.setUserName(user.getUserName());
        communityPostVO.setUserAvatar(user.getUserAvatar());
        communityPostVO.setUserProfile(user.getUserProfile());
        // 查询当前用户的所有文章, 用于设置用户的其他文章
        List<CommunityPost> list = lambdaQuery()
                .eq(CommunityPost::getUserId, user.getId())
                .ne(CommunityPost::getId, communityPost.getId())
                .eq(CommunityPost::getReviewStatus, PostStatusEnum.PASS.getValue())
                .eq(CommunityPost::getIsDelete, 0)
                .list();
        List<PostDetailVO> postDetailVOList = new ArrayList<>(list.size());
        if (CollUtil.isNotEmpty(list)){
            communityPostVO.setPostNumber((long) (list.size() + 1));
            list.forEach((item) -> {
                PostDetailVO postDetailVO = BeanUtils.copyBean(item, PostDetailVO.class);
                postDetailVOList.add(postDetailVO);
            });
            communityPostVO.setPostDetailVOList(postDetailVOList);
        }
        // 4.设置标签信息
        List<String> tagsList = postTagService.lambdaQuery()
                .eq(PostTag::getPostId, communityPost.getId())
                .list().stream().map(PostTag::getCategory).collect(Collectors.toList());
        communityPostVO.setTagList(tagsList);
        // 5.设置社区信息
        if (communityPost.getCommunityId() == null){
            communityPostVO.setCommunityName("灵图公社");
        }
        // 6.当前用户是否点赞
        communityPostVO.setHasLiked(false);
        communityPostVO.setHasFavorited(false);
        // 7.增加浏览数
        lambdaUpdate()
                .eq(CommunityPost::getId, communityPost.getId())
                .setSql("viewCount = viewCount + 5")
                .update();
        communityPostVO.setViewCount(communityPostVO.getViewCount());

        return communityPostVO;
    }

    @Override
    public Page<CommunityPostVO> listCommunityPostVOByPage(CommunityPostQueryRequest communityPostQueryRequest,
            HttpServletRequest request) {
        // 1.获取分页查询条件
        Long communityId = communityPostQueryRequest.getCommunityId();
        List<String> tags = communityPostQueryRequest.getTags();
        Boolean hotOrder = communityPostQueryRequest.getHotOrder();
        String searchText = communityPostQueryRequest.getSearchText();
        LambdaQueryWrapper<CommunityPost> queryWrapper = new LambdaQueryWrapper<>();
        // 2.查询关联的所有标签
        // 2.1.获取涉及的所有标签
        if (CollUtil.isNotEmpty(tags)){
            List<Tag> tagList = new ArrayList<>(tags.size());
            List<Long> tagIds = new ArrayList<>(tags.size());
            List<Long> postIds = new ArrayList<>(tags.size());
            for (String tag : tags) {
                Tag tag1 = tagService.getByCategory(tag);
                tagList.add(tag1);
            }
            if (CollUtil.isNotEmpty(tagList)){
                tagIds = tagList.stream().map(Tag::getId).collect(Collectors.toList());

                // 2.2.查询标签关联的帖子id
                postIds = postTagService.lambdaQuery()
                        .in(PostTag::getTagId, tagIds)
                        .list().stream().map(PostTag::getPostId).collect(Collectors.toList());
            }
            // 设置关联标签的查询条件
            queryWrapper.in(!CollUtil.isEmpty(postIds), CommunityPost::getId, postIds);
        }
        // 3.设置查询条件
        // 从多字段中搜索
        if (StrUtil.isNotBlank(searchText)) {
            // 需要拼接查询条件
            // and (title like "%xxx%" or summary like "%xxx%")
            queryWrapper.and(
                    qw -> qw.like(CommunityPost::getTitle, searchText)
                            .or()
                            .like(CommunityPost::getSummary, searchText)
            );
        }
        queryWrapper.eq(communityId != null, CommunityPost::getCommunityId, communityId);
        // 3.1.设置查询展示排序
        queryWrapper.orderByDesc(hotOrder != null && hotOrder, CommunityPost::getLikeCount);
        // 4.分页查询
        Page<CommunityPost> page = new Page<>(communityPostQueryRequest.getCurrent(), communityPostQueryRequest.getPageSize());
        Page<CommunityPost> resultPages = this.page(page, queryWrapper);
        List<CommunityPost> records = resultPages.getRecords();
        if (CollUtil.isEmpty(records)){
            return Page.of(communityPostQueryRequest.getCurrent(), communityPostQueryRequest.getPageSize(), 0L);
        }
        // 5.封装为vo
        List<CommunityPostVO> voList = new ArrayList<>(records.size());
        // 5.1.获取相关用户信息
        Set<Long> userIds = new HashSet<>(records.size());
        Map<Long, User> uMap = new HashMap<>(records.size());
        for (CommunityPost record : records) {
            userIds.add(record.getUserId());
        }
        List<User> userList = userService.getUserListByIds(userIds);

        if (CollUtil.isNotEmpty(userList)){
            uMap = userList.stream().collect(Collectors.toMap(User::getId, user -> user));
        }
        // todo 5.2.判断当前用户是否点赞、收藏。 先忽略，后续调方法
        for (CommunityPost record : records) {
            if (record.getIsDelete() == 1) continue;
            // 5.3.转换为vo
            CommunityPostVO vo = BeanUtils.copyBean(record, CommunityPostVO.class);
            Long userId = record.getUserId();
            vo.setUserId(uMap.get(userId).getId());
            vo.setUserName(uMap.get(userId).getUserName());
            vo.setUserAvatar(uMap.get(userId).getUserAvatar());
            vo.setCreateTime(record.getCreateTime());
            if (record.getCommunityId() == null){
                vo.setCommunityName("灵图公社");
            }
            // 5.4.填充关联的标签
            List<String> tagList1 = postTagService.lambdaQuery()
                    .eq(PostTag::getPostId, record.getId())
                    .list().stream().map(PostTag::getCategory).collect(Collectors.toList());
            vo.setTagList(tagList1);
            // todo 5.5.先默认为未点赞、未收藏
            vo.setHasLiked(false);
            vo.setHasFavorited(false);

            voList.add(vo);
        }
        // 封装返回值
        Page<CommunityPostVO> resultPageVO = new Page<>();
        resultPageVO.setCurrent(resultPages.getCurrent());
        resultPageVO.setSize(resultPages.getSize());
        resultPageVO.setTotal(resultPages.getTotal());
        resultPageVO.setRecords(voList);
        return resultPageVO;
    }

    @Override
    @Transactional
    public Long addCommunityPost(CommunityPostAddRequest communityPostAddRequest, User loginUser) {
        // 1. 校验参数
        ThrowUtils.throwIf(loginUser == null, ErrorCode.NO_AUTH_ERROR);
        // 2. 获取当前登录用户id
        Long userId = loginUser.getId();
        UserRoleEnum userRoleEnum = UserRoleEnum.getEnumByValue(loginUser.getUserRole());
        // 3.属性拷贝
        CommunityPost communityPost = BeanUtils.copyBean(communityPostAddRequest, CommunityPost.class);
        if (userId != null && userRoleEnum.equals(UserRoleEnum.ADMIN)) {
            communityPost.setReviewMessage(PASSED_IF_ADMIN);
            communityPost.setReviewStatus(1);
            communityPost.setReviewTime(LocalDateTime.now());
            communityPost.setReviewerId(userId);
        }
        communityPost.setUserId(userId);

        // 5.创建文章
        this.save(communityPost);
        // 6.创建文章标签关联表
        List<PostTag> postTagList = new ArrayList<>();
        List<String> tags = communityPostAddRequest.getTags();
        for (String category : tags) {
            Tag tag = tagService.getByCategory(category);
            PostTag postTag = new PostTag();
            postTag.setPostId(communityPost.getId());
            postTag.setTagId(tag.getId());
            postTag.setCategory(category);
            postTag.setName(tag.getName());
            postTagList.add(postTag);
        }
        // 7.批量插入
        postTagService.saveBatch(postTagList);

        return communityPost.getId();
    }

    @Override
    public boolean updateCommunityPost(CommunityPostEditRequest communityPostEditRequest, User loginUser) {
        // 1. 校验参数
        ThrowUtils.throwIf(communityPostEditRequest == null || communityPostEditRequest.getId() == null,
                ErrorCode.PARAMS_ERROR);
        ThrowUtils.throwIf(loginUser == null, ErrorCode.NO_AUTH_ERROR);

        // 2. 查询原文章是否存在
        Long postId = communityPostEditRequest.getId();
        CommunityPost oldPost = this.getById(postId);
        ThrowUtils.throwIf(oldPost == null, ErrorCode.NOT_FOUND_ERROR, "文章不存在");

        // 3. 权限校验 - 只有作者或管理员可以编辑
        Long userId = loginUser.getId();
        UserRoleEnum userRoleEnum = UserRoleEnum.getEnumByValue(loginUser.getUserRole());
        boolean isAdmin = userRoleEnum.equals(UserRoleEnum.ADMIN);

        if (!oldPost.getUserId().equals(userId) && !isAdmin) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "没有编辑权限");
        }

        CommunityPost communityPost = BeanUtils.copyBean(communityPostEditRequest, CommunityPost.class);
        // 5. 审核相关处理
        if (isAdmin) {
            communityPost.setReviewMessage(PASSED_IF_ADMIN);
            communityPost.setReviewStatus(1);
            communityPost.setReviewTime(LocalDateTime.now());
            communityPost.setReviewerId(userId);
        }
        // 6. 更新文章
        return this.updateById(communityPost);
    }

    @Override
    public boolean deleteCommunityPost(Long id, User loginUser) {

        return false;
    }

    @Override
    public boolean favoriteCommunityPost(Long id, User loginUser) {
        return false;
    }

    @Override
    public boolean unfavoriteCommunityPost(Long id, User loginUser) {
        return false;
    }

    @Override
    public QueryWrapper<CommunityPost> getQueryWrapper(CommunityPostQueryRequest communityPostQueryRequest) {
        return null;
    }

    @Override
    public String uploadPicture(MultipartFile multipartFile, User loginUser) {
        // 4. 处理图片上传
        if (multipartFile != null && !multipartFile.isEmpty()) {
            // 上传新图片到对象存储
            String uploadPathPrefix = String.format("community/post/%s", loginUser.getId());;
            try {
                // 使用现有的图片上传模板
                UploadPictureResult uploadResult = filePictureUpload.uploadPicture(multipartFile, uploadPathPrefix);
                // 将图片URL保存到文章对象中
                return uploadResult.getUrl();
            } catch (Exception e) {
                log.error("图片上传失败", e);
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "图片上传失败");
            }
        } else {
            // 如果没有新上传的图片，保留原图片URL
            return null;
        }
    }
}
